/**
 * Created by hjqi on 2016/5/5.
 */
/*var httpRequest = require('../common/httpRequest').httpRequest;
var _req = new httpRequest();*/
var libK8s = require('../k8s/kubernetes');
//var _k8s = new libK8s();
var _k8s_adp = require('../k8s/k8sAdpter');
//var _k8s_promise = _k8s_adp.getK8s();
var libJenkins = require('../jenkins/jenkins');
var _jenkins = new libJenkins();
var libUserAccount = require('./userAccount');
var _userAccount = new libUserAccount();
var UserBasicInfoDB = require('../../db/userBasicInfoDB');
var _userInfodb = new UserBasicInfoDB();
var logger = require('../log4js/log4js').logger('user');
var Common = require('../common/common');
var emptyPromise = Common.emptyPromise;
var bcrypt = require('../common/bcrypt'),
    baseDbInfo = require('../../db/baseDbInfo'),
    collectionName = require('../config/config').config.mongodb.users_collection ,
    baseCollector = new baseDbInfo( collectionName ) ;


module.exports = libUser;

function libUser(){

}
/**
 * create user procedures like below:
 * 1.jenkins.createView()->
 * 2.insertUserInDB -> insert a record to collection userBasicInfo
 * 3.userAccount.createAccountInfo ->  insert a record to collection  userAccountInfo
 * @by bfxer
 */
libUser.prototype.createUser = function(userInfo){

    var username = userInfo.username;
    var _self = this;
    return new Promise(function (resolve, reject) {
        var _rollback_stack = [];
        var _k8s;
        //create k8s namespace not put create k8s ns in create user process
        _k8s_adp.getK8s().then(function(ret_k8s) {
            _k8s = ret_k8s;
            return _k8s.createNameSpace(username);
        }).then(function(){
            _rollback_stack.push({
                fn:_k8s.deleteNameSpace,
                args:[username]
            });
            //create jenkins view
            return _jenkins.createView(username);
        })
        //_jenkins.createView(username)
        //insert db
        .then(function(){

            _rollback_stack.push({
                fn:_jenkins.deleteView,
                args:[username]
            });
            return insertUserInDB(userInfo);
        }).then(function(){

            _rollback_stack.push({
                fn:deleteUserInDB,
                args:[username]
            });
            return _userAccount.createAccountInfo(username);
        }).then(function(){
            //finish
            resolve(true);
        }).catch(function(err){
            //rollback
            logger.error("jenkins failed:"+JSON.stringify( err )) ;
            rollback(_self,_rollback_stack)
            reject(false);
        })
    });
}

libUser.prototype.deleteUser = function(userInfo){
    var username = userInfo.username ;
    return deleteUserInDB(username) ;
}

libUser.prototype.getBasicAuthenToken = function(username) {
    return new Promise(function (resolve, reject) {
        findUser(username).then(function ( ret) {
            //logger.debug("token result"+JSON.stringify( ret )) ;
            //ret: [{
            //     "username" : "nature01",
            //     "password" : "1d6010cd9dbd82777851c19ef1e2b70f",
            //     "pullSecr" : "bmF0dXJlMDE6bmF0dXJlMDE=",
            //     "company" : "anonymous1",
            //     "identifyingCode" : "5754",
            //     "phoneNumber" : "15384049487",
            //     "_id" : "57edd7c189c9eba021714ba5"
            // } ]
            if( ret && ret.length > 0){
                var name = ret[0].username ;
                var pass = ret[0].password ;
                var b = new Buffer( name+":"+pass );

                resolve(  b.toString('base64') ) ;
            }else{
                logger.warn("#getBasicAuthenToken:can't get user basic info,maybe user did't exist,user="+username) ;
                reject("No user info exist!") ;
            }
        }).catch(function ( err ) {
            logger.error("#getBasicAuthenToken:can't get token",err) ;
            reject() ;
        }) ;
    }) ;
}

libUser.prototype.updateUser = function ( userQuery,updateFields ) {
    return updateUserBasicInfo(userQuery,updateFields) ;
}

libUser.prototype.insertAuthInfo = function(userInfo){
    return insertUserAuthInfo( userInfo ) ;
}

libUser.prototype.updateAuthInfo = function ( userInfo ) {
    return updateAuthInfo(userInfo) ;
}

libUser.prototype.existAuthInfo = function ( username ) {
    return new Promise(function (resolve,reject) {
        findAuth(username).then(function () {
            resolve(true);
        }).catch(function (err) {
            resolve(false);
        }) ;
    }) ;
}


function updateUserBasicInfo(userQuery,updateFields){
    userQuery = userQuery||{} ;
    updateFields = updateFields||{} ;

    //更新用户用户信息
    if( !updateFields.$set ){
        updateFields = {
            $set: updateFields
        } ;
    }

    return new Promise( function ( resolve ,reject) {
        _userInfodb.updateWithParam(null, userQuery, updateFields, function (err) {
            if (err) {
                reject( err )
                logger.error("[#updateUserBasicInfo]" + username + "出错：" ,err);
            } else {
                resolve(true) ;
            }
        })
    }) ;
}

function rollback(ctx,stack){
    stack.forEach(function(exec){
        var fn = exec.fn;
        fn.apply(ctx,exec.args);
    });
}

/**
 * 创建用户信息
 * TODO 用户registry认证信息
 */
function insertUserInDB(user){
    return new Promise(function(_resolve, _reject){
        _userInfodb.insert(null ,user,function(err){
            logger.debug("#insertUserInDB:err="+JSON.stringify( err )) ;
            if(err){
                _reject(err);
            }else{
                //创建用户的认证信息，确保用户密码已经是加密之后的密码
                insertUserAuthInfo( user ).then(function () {
                    _resolve(true);
                }).catch(function ( err ) {
                    var username = user.username ;
                    logger.error( "#insertUserInDB:err="+JSON.stringify( err )) ;
                    userInsertionRollback( username ) ;
                    _reject(err);
                }) ;
            }
        });
    });
}

//delete the user for remediation
function userInsertionRollback( username ){
    deleteUserInDB( username ).then( function () {
        logger.info("[#insertUserInDB]rollback to delete the user succeeded.") ;
    }).catch(function ( err ) {
        logger.error("[#insertUserInDB]rollback to delete the user but failed.") ;
    }) ; //roll back
}
/**
 * 插入用户认证信息
 * userInfo:
 * {
    "username" : "system",
    "password" : "e10adc3949ba59abbe56e057f20f883e",
    "company" : "鏉窞瀹逛簯缃戠粶绉戞妧鏈夐檺鍏徃",
    "_id" : ObjectId("57a5de729b0625ac4f92333d")
}
 */
function insertUserAuthInfo(userInfo){
    var username = userInfo.username ;
    var password = ""  ;//BCrypt hash

    logger.debug("insertUserAuthInfo.pass"+ userInfo.bHash ) ;
    if( userInfo.bHash ){
        password = userInfo.bHash ;
    }else{
       //deprecated password= bcrypt.getBcryptHashStr( userInfo.password );
        return emptyPromise();
    }

    var data = {
        "username": username ,
        "password":password
    }
    return new Promise(function(_resolve, _reject){
        baseCollector.insert(null ,data,function(err){
            logger.debug("#insertUserAuthInfo:err="+JSON.stringify( err )) ;
            if(err){
                logger.error( "#insertUserAuthInfo:err="+err.message ) ;
                _reject(err);
            }else{
                _resolve(true);
            }
        });
    });
}
/**
 *  更新用户认证信息
 */
function updateAuthInfo(userInfo){
    logger.debug("updateAuthInfo.pass"+ userInfo.bHash ) ;
    if( !userInfo.bHash){
        return ;
    }
    var username = userInfo.username ;
    var password = userInfo.bHash;// =  bcrypt.getBcryptHashStr( userInfo.password ) ;//BCrypt hash
    var query = { "username": username  }
    var updateFields = {
        $set : {
            'password' : password
        }
    }


    return new Promise(function(_resolve, _reject){
        baseCollector.updateWithParam(null, query, updateFields, function (err) {
            logger.debug("#insertUserAuthInfo:err="+JSON.stringify( err )) ;
            if(err){
                logger.error( "#insertUserAuthInfo:err="+JSON.stringify( err )) ;
                _reject(err);
            }else{
                _resolve(true);
            }
        });
    });
}

function deleteUserInDB(username){
    return new Promise(function(_resolve, _reject){
        _userInfodb.delWithParam(null,{username:username},function(err){
            if(err){
                logger.error( "#deleteUserInDB:err="+JSON.stringify( err )) ;
                _reject(err);
            }else{
                _resolve(true);
            }
        });
    });
}
/**
 * 根据用户名查找用户
 */
function findUser(username){
    return new Promise(function(_resolve, _reject){
        _userInfodb.getWithParam(null,{username:username},function(err,rets){
            if(err){
                logger.error("#findUser:Can't get user info",err) ;
                _reject(err);
            }else{
                _resolve(rets);
            }
        });
    });
}
/**
 * 查找用户的认证信息
 */
function findAuth(username){
    return new Promise(function(_resolve, _reject){
            baseCollector.getWithParam(null,{username:username},function(err,rets){
                if(err || !rets || rets.length == 0){
                    logger.error("#findAuth:Can't get user auth info",err) ;
                    _reject(err);
                }else{
                    logger.debug("#findAuth:"+JSON.stringify( rets )) ;
                    _resolve(true);
                }
            });
    });
}
